package com.hsjk.szwj.module.pay.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hsjk.szwj.framework.common.constant.CommonConstant;
import com.hsjk.szwj.framework.tenant.core.aop.TenantIgnore;
import com.hsjk.szwj.module.pay.constant.PayOrderConstant;
import com.hsjk.szwj.module.pay.dal.dataobject.order.PayOrderDO;
import com.hsjk.szwj.module.pay.dal.mysql.IIsvInfoMapper;
import com.hsjk.szwj.module.pay.dal.mysql.IMchInfoMapper;
import com.hsjk.szwj.module.pay.dal.mysql.IPayOrderDivisionRecordMapper;
import com.hsjk.szwj.module.pay.dal.mysql.IPayOrderMapper;
import com.hsjk.szwj.module.pay.dal.mysql.IPayWayMapper;
import com.hsjk.szwj.module.pay.util.AmountUtil;
import com.hsjk.szwj.module.train.api.dto.DivisionReceiverDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author chenjiawei
 * @desc
 * @Date 2023/08/22 01:10
 **/
@Service
public class PayOrderService extends ServiceImpl<IPayOrderMapper, PayOrderDO> {
    @Resource
    private IPayOrderMapper payOrderMapper;
    @Resource
    private IMchInfoMapper mchInfoMapper;
    @Resource
    private IIsvInfoMapper isvInfoMapper;
    @Resource
    private IPayWayMapper payWayMapper;
    @Resource
    private IPayOrderDivisionRecordMapper payOrderDivisionRecordMapper;


    @TenantIgnore
    public Long getTenant(Long id) {
        Long tenantId = null;
        PayOrderDO payOrderDO = payOrderMapper.selectById(id);
        if (ObjectUtil.isNotNull(payOrderDO)) {
            tenantId = payOrderDO.getTenantId();
        }
        return tenantId;
    }

    /**
     * 更新订单状态  【订单生成】 --》 【支付中】
     **/
    public boolean updateInit2Ing(Long payOrderId, PayOrderDO payOrder) {

        PayOrderDO updateRecord = new PayOrderDO();
        updateRecord.setState(PayOrderConstant.STATE_ING);

        //同时更新， 未确定 --》 已确定的其他信息。  如支付接口的确认、 费率的计算。
        updateRecord.setIfId(payOrder.getIfId());
        updateRecord.setWayCode(payOrder.getWayCode());
        updateRecord.setMchFeeRate(payOrder.getMchFeeRate());
        updateRecord.setMchFeeAmount(payOrder.getMchFeeAmount());
        updateRecord.setChannelUser(payOrder.getChannelUser());
        updateRecord.setChannelOrderNo(payOrder.getChannelOrderNo());

        return update(updateRecord, new LambdaUpdateWrapper<PayOrderDO>()
                .eq(PayOrderDO::getId, payOrderId)
                .eq(PayOrderDO::getState, PayOrderConstant.STATE_INIT));
    }

    /**
     * 更新订单状态  【支付中】 --》 【支付成功】
     **/
    public boolean updateIng2Success(Long payOrderId, String channelOrderNo, String channelUserId) {

        PayOrderDO updateRecord = new PayOrderDO();
        updateRecord.setState(PayOrderConstant.STATE_SUCCESS);
        updateRecord.setChannelOrderNo(channelOrderNo);
        updateRecord.setChannelUser(channelUserId);
        updateRecord.setSuccessTime(LocalDateTime.now());

        return update(updateRecord, new LambdaUpdateWrapper<PayOrderDO>()
                .eq(PayOrderDO::getId, payOrderId)
                .eq(PayOrderDO::getState, PayOrderConstant.STATE_ING));
    }

    /**
     * 更新订单状态  【支付中】 --》 【订单关闭】
     **/
    public boolean updateIng2Close(Long payOrderId) {

        PayOrderDO updateRecord = new PayOrderDO();
        updateRecord.setState(PayOrderConstant.STATE_CLOSED);

        return update(updateRecord, new LambdaUpdateWrapper<PayOrderDO>()
                .eq(PayOrderDO::getId, payOrderId)
                .eq(PayOrderDO::getState, PayOrderConstant.STATE_ING));
    }

    /**
     * 更新订单状态  【订单生成】 --》 【订单关闭】
     **/
    public boolean updateInit2Close(Long payOrderId) {

        PayOrderDO updateRecord = new PayOrderDO();
        updateRecord.setState(PayOrderConstant.STATE_CLOSED);

        return update(updateRecord, new LambdaUpdateWrapper<PayOrderDO>()
                .eq(PayOrderDO::getId, payOrderId)
                .eq(PayOrderDO::getState, PayOrderConstant.STATE_INIT));
    }


    /**
     * 更新订单状态  【支付中】 --》 【支付失败】
     **/
    public boolean updateIng2Fail(Long payOrderId, String channelOrderNo,
                                  String channelUserId, String channelErrCode,
                                  String channelErrMsg) {

        PayOrderDO updateRecord = new PayOrderDO();
        updateRecord.setState(PayOrderConstant.STATE_FAIL);
        updateRecord.setErrCode(channelErrCode);
        updateRecord.setErrMsg(channelErrMsg);
        updateRecord.setChannelOrderNo(channelOrderNo);
        updateRecord.setChannelUser(channelUserId);

        return update(updateRecord, new LambdaUpdateWrapper<PayOrderDO>()
                .eq(PayOrderDO::getId, payOrderId)
                .eq(PayOrderDO::getState, PayOrderConstant.STATE_ING));
    }


    /**
     * 更新订单状态  【支付中】 --》 【支付成功/支付失败】
     **/
    public boolean updateIng2SuccessOrFail(Long payOrderId, Integer updateState,
                                           String channelOrderNo, String channelUserId,
                                           String channelErrCode, String channelErrMsg) {

        if (updateState == PayOrderConstant.STATE_ING) {
            return true;
        } else if (updateState == PayOrderConstant.STATE_SUCCESS) {
            return updateIng2Success(payOrderId, channelOrderNo, channelUserId);
        } else if (updateState == PayOrderConstant.STATE_FAIL) {
            return updateIng2Fail(payOrderId, channelOrderNo, channelUserId, channelErrCode, channelErrMsg);
        }
        return false;
    }

    /**
     * 查询商户订单
     **/
    public PayOrderDO queryMchOrder(Long mchId, Long payOrderId, Long mchOrderId) {

        if (payOrderId != null) {
            return getOne(new LambdaQueryWrapper<PayOrderDO>()
                    .eq(PayOrderDO::getMchId, mchId)
                    .eq(PayOrderDO::getId, payOrderId));
        } else if (ObjectUtil.isNotNull(mchOrderId)) {
            return getOne(new LambdaQueryWrapper<PayOrderDO>()
                    .eq(PayOrderDO::getMchId, mchId)
                    .eq(PayOrderDO::getMchOrderId, mchOrderId));
        } else {
            return null;
        }
    }


    public Map payCount(Long mchId, Integer state, Integer refundState,
                        String dayStart, String dayEnd) {
        Map param = new HashMap<>();
        if (state != null) {
            param.put("state", state);
        }
        if (refundState != null) {
            param.put("refundState", refundState);
        }
        if (ObjectUtil.isNotNull(mchId)) {
            param.put("mchId", mchId);
        }
        if (StrUtil.isNotBlank(dayStart)) {
            param.put("createTimeStart", dayStart);
        }
        if (StrUtil.isNotBlank(dayEnd)) {
            param.put("createTimeEnd", dayEnd);
        }
        return payOrderMapper.payCount(param);
    }

    public List<Map> payTypeCount(Long mchId, Integer state, Integer refundState,
                                  String dayStart, String dayEnd) {
        Map param = new HashMap<>();
        if (state != null) {
            param.put("state", state);
        }
        if (refundState != null) {
            param.put("refundState", refundState);
        }
        if (ObjectUtil.isNotNull(mchId)) {
            param.put("mchId", mchId);
        }
        if (StrUtil.isNotBlank(dayStart)) {
            param.put("createTimeStart", dayStart);
        }
        if (StrUtil.isNotBlank(dayEnd)) {
            param.put("createTimeEnd", dayEnd);
        }
        return payOrderMapper.payTypeCount(param);
    }

    /**
     * 更新订单为 超时状态
     **/
    public Integer updateOrderExpired() {

        PayOrderDO payOrder = new PayOrderDO();
        payOrder.setState(PayOrderConstant.STATE_CLOSED);

        return baseMapper.update(payOrder,
                new LambdaQueryWrapper<PayOrderDO>()
                        .in(PayOrderDO::getState,
                                Arrays.asList(PayOrderConstant.STATE_INIT,
                                        PayOrderConstant.STATE_ING))
                        .le(PayOrderDO::getExpiredTime, LocalDateTime.now())
        );
    }

    /**
     * 更新订单 通知状态 --> 已发送
     **/
    public int updateNotifySent(Long payOrderId) {
        PayOrderDO payOrder = new PayOrderDO();
        payOrder.setNotifyState(CommonConstant.YES);
        payOrder.setId(payOrderId);
        return baseMapper.updateById(payOrder);
    }

    /**
     * 首页支付周统计
     **/
//    public JSONObject mainPageWeekCount(String mchNo) {
//        JSONObject json = new JSONObject();
//        Map dayAmount = new LinkedHashMap();
//        ArrayList array = new ArrayList<>();
//        BigDecimal payAmount = new BigDecimal(0);    // 当日金额
//        BigDecimal payWeek = payAmount;   // 周总收益
//        String todayAmount = "0.00";    // 今日金额
//        String todayPayCount = "0";    // 今日交易笔数
//        String yesterdayAmount = "0.00";    // 昨日金额
//        Date today = new Date();
//        for (int i = 0; i < 7; i++) {
//            Date date = DateUtil.offsetDay(today, -i).toJdkDate();
//            String dayStart = DateUtil.beginOfDay(date).toString(DatePattern.NORM_DATETIME_MINUTE_PATTERN);
//            String dayEnd = DateUtil.endOfDay(date).toString(DatePattern.NORM_DATETIME_MINUTE_PATTERN);
//            // 每日交易金额查询
//            dayAmount = payCount(mchNo, PayOrder.STATE_SUCCESS, null, dayStart, dayEnd);
//            if (dayAmount != null) {
//                payAmount = new BigDecimal(dayAmount.get("payAmount").toString());
//            }
//            if (i == 0) {
//                todayAmount = dayAmount.get("payAmount").toString();
//                todayPayCount = dayAmount.get("payCount").toString();
//            }
//            if (i == 1) {
//                yesterdayAmount = dayAmount.get("payAmount").toString();
//            }
//            payWeek = payWeek.add(payAmount);
//            array.add(payAmount);
//        }
//
//        // 倒序排列
//        Collections.reverse(array);
//        json.put("dataArray", array);
//        json.put("todayAmount", todayAmount);
//        json.put("todayPayCount", todayPayCount);
//        json.put("payWeek", payWeek);
//        json.put("yesterdayAmount", yesterdayAmount);
//        return json;
//    }

    /**
     * 首页统计总数量
     **/
//    public JSONObject mainPageNumCount(String mchNo) {
//        JSONObject json = new JSONObject();
//        // 商户总数
//        int mchCount = mchInfoMapper.selectCount(MchInfo.gw());
//        // 服务商总数
//        int isvCount = isvInfoMapper.selectCount(IsvInfo.gw());
//        // 总交易金额
//        Map<String, String> payCountMap = payCount(mchNo, PayOrder.STATE_SUCCESS, null, null, null);
//        json.put("totalMch", mchCount);
//        json.put("totalIsv", isvCount);
//        json.put("totalAmount", payCountMap.get("payAmount"));
//        json.put("totalCount", payCountMap.get("payCount"));
//        return json;
//    }

    /**
     * 首页支付统计
     **/
//    public List<Map> mainPagePayCount(String mchNo, String createdStart, String createdEnd) {
//        Map param = new HashMap<>(); // 条件参数
//        int daySpace = 6; // 默认最近七天（含当天）
//        if (StringUtils.isNotEmpty(createdStart) && StringUtils.isNotEmpty(createdEnd)) {
//            createdStart = createdStart + " 00:00:00";
//            createdEnd = createdEnd + " 23:59:59";
//            // 计算两时间间隔天数
//            daySpace = Math.toIntExact(DateUtil.betweenDay(DateUtil.parseDate(createdStart), DateUtil.parseDate(createdEnd), true));
//        } else {
//            Date today = new Date();
//            createdStart = DateUtil.formatDate(DateUtil.offsetDay(today, -daySpace)) + " 00:00:00";
//            createdEnd = DateUtil.formatDate(today) + " 23:59:59";
//        }
//
//        if (StrUtil.isNotBlank(mchNo)) {
//            param.put("mchNo", mchNo);
//        }
//        param.put("createTimeStart", createdStart);
//        param.put("createTimeEnd", createdEnd);
//        // 查询收款的记录
//        List<Map> payOrderList = payOrderMapper.selectOrderCount(param);
//        // 查询退款的记录
//        List<Map> refundOrderList = payOrderMapper.selectOrderCount(param);
//        // 生成前端返回参数类型
//        List<Map> returnList = getReturnList(daySpace, createdEnd, payOrderList, refundOrderList);
//        return returnList;
//    }

    /**
     * 首页支付类型统计
     **/
//    public ArrayList mainPagePayTypeCount(String mchNo, String createdStart, String createdEnd) {
//        // 返回数据列
//        ArrayList array = new ArrayList<>();
//        if (StringUtils.isNotEmpty(createdStart) && StringUtils.isNotEmpty(createdEnd)) {
//            createdStart = createdStart + " 00:00:00";
//            createdEnd = createdEnd + " 23:59:59";
//        } else {
//            Date endDay = new Date();    // 当前日期
//            Date startDay = DateUtil.lastWeek().toJdkDate(); // 一周前日期
//            String end = DateUtil.formatDate(endDay);
//            String start = DateUtil.formatDate(startDay);
//            createdStart = start + " 00:00:00";
//            createdEnd = end + " 23:59:59";
//        }
//        // 统计列表
//        List<Map> payCountMap = payTypeCount(mchNo, PayOrder.STATE_SUCCESS, null, createdStart, createdEnd);
//
//        // 得到所有支付方式
//        Map<String, String> payWayNameMap = new HashMap<>();
//        List<PayWay> payWayList = payWayMapper.selectList(PayWay.gw());
//        for (PayWay payWay : payWayList) {
//            payWayNameMap.put(payWay.getWayCode(), payWay.getWayName());
//        }
//        // 支付方式名称标注
//        for (Map payCount : payCountMap) {
//            if (StringUtils.isNotEmpty(payWayNameMap.get(payCount.get("wayCode")))) {
//                payCount.put("typeName", payWayNameMap.get(payCount.get("wayCode")));
//            } else {
//                payCount.put("typeName", payCount.get("wayCode"));
//            }
//        }
//        array.add(payCountMap);
//        return array;
//    }

    /**
     * 生成首页交易统计数据类型
     **/
//    public List<Map> getReturnList(int daySpace, String createdStart, List<Map> payOrderList, List<Map> refundOrderList) {
//        List<Map> dayList = new ArrayList<>();
//        DateTime endDay = DateUtil.parseDateTime(createdStart);
//        // 先判断间隔天数 根据天数设置空的list
//        for (int i = 0; i <= daySpace; i++) {
//            Map<String, String> map = new HashMap<>();
//            map.put("date", DateUtil.format(DateUtil.offsetDay(endDay, -i), "MM-dd"));
//            dayList.add(map);
//        }
//        // 日期倒序排列
//        Collections.reverse(dayList);
//
//        List<Map> payListMap = new ArrayList<>(); // 收款的列
//        List<Map> refundListMap = new ArrayList<>(); // 退款的列
//        for (Map dayMap : dayList) {
//            // 为收款列和退款列赋值默认参数【payAmount字段切记不可为string，否则前端图表解析不出来】
//            Map<String, Object> payMap = new HashMap<>();
//            payMap.put("date", dayMap.get("date").toString());
//            payMap.put("type", "收款");
//            payMap.put("payAmount", 0);
//
//            Map<String, Object> refundMap = new HashMap<>();
//            refundMap.put("date", dayMap.get("date").toString());
//            refundMap.put("type", "退款");
//            refundMap.put("payAmount", 0);
//            for (Map payOrderMap : payOrderList) {
//                if (dayMap.get("date").equals(payOrderMap.get("groupDate"))) {
//                    payMap.put("payAmount", payOrderMap.get("payAmount"));
//                }
//            }
//            payListMap.add(payMap);
//            for (Map refundOrderMap : refundOrderList) {
//                if (dayMap.get("date").equals(refundOrderMap.get("groupDate"))) {
//                    refundMap.put("payAmount", refundOrderMap.get("refundAmount"));
//                }
//            }
//            refundListMap.add(refundMap);
//        }
//        payListMap.addAll(refundListMap);
//        return payListMap;
//    }


    /**
     * 计算支付订单商家入账金额
     * 商家订单入账金额 （支付金额 - 手续费 - 退款金额 - 总分账金额）
     *
     * @author terrfly
     * @site https://www.jeequan.com
     * @date 2021/8/26 16:39
     */
//    public Long calMchIncomeAmount(PayOrder dbPayOrder) {
//
//        //商家订单入账金额 （支付金额 - 手续费 - 退款金额 - 总分账金额）
//        Long mchIncomeAmount = dbPayOrder.getAmount() - dbPayOrder.getMchFeeAmount() - dbPayOrder.getRefundAmount();
//
//        //减去已分账金额
//        mchIncomeAmount -= payOrderDivisionRecordMapper.sumSuccessDivisionAmount(dbPayOrder.getPayOrderId());
//
//        return mchIncomeAmount <= 0 ? 0 : mchIncomeAmount;
//
//    }

    /**
     * 通用列表查询条件
     *
     * @param iPage
     * @param payOrder
     * @param paramJSON
     * @param wrapper
     * @return
     */
    public IPage<PayOrderDO> listByPage(IPage iPage, PayOrderDO payOrder,
                                        JSONObject paramJSON,
                                        LambdaQueryWrapper<PayOrderDO> wrapper) {
        if (payOrder.getId() != null) {
            wrapper.eq(PayOrderDO::getId, payOrder.getId());
        }
        if (payOrder.getMchId() != null) {
            wrapper.eq(PayOrderDO::getMchId, payOrder.getMchId());
        }
        if (payOrder.getIsvId() != null) {
            wrapper.eq(PayOrderDO::getIsvId, payOrder.getIsvId());
        }
        if (payOrder.getMchType() != null) {
            wrapper.eq(PayOrderDO::getMchType, payOrder.getMchType());
        }
        if (StringUtils.isNotEmpty(payOrder.getWayCode())) {
            wrapper.eq(PayOrderDO::getWayCode, payOrder.getWayCode());
        }
        if (payOrder.getMchOrderId() != null) {
            wrapper.eq(PayOrderDO::getMchOrderId, payOrder.getMchOrderId());
        }
        if (payOrder.getState() != null) {
            wrapper.eq(PayOrderDO::getState, payOrder.getState());
        }
        if (payOrder.getNotifyState() != null) {
            wrapper.eq(PayOrderDO::getNotifyState, payOrder.getNotifyState());
        }
        if (payOrder.getAppId() != null) {
            wrapper.eq(PayOrderDO::getAppId, payOrder.getAppId());
        }
        if (payOrder.getDivisionState() != null) {
            wrapper.eq(PayOrderDO::getDivisionState, payOrder.getDivisionState());
        }
        if (paramJSON != null) {
            if (StringUtils.isNotEmpty(paramJSON.getStr("createdStart"))) {
                wrapper.ge(PayOrderDO::getCreateTime, paramJSON.getStr("createdStart"));
            }
            if (StringUtils.isNotEmpty(paramJSON.getStr("createdEnd"))) {
                wrapper.le(PayOrderDO::getCreateTime, paramJSON.getStr("createdEnd"));
            }
        }
        // 三合一订单
        if (paramJSON != null && StringUtils.isNotEmpty(paramJSON.getStr("unionOrderId"))) {
            wrapper.and(wr -> {
                wr.eq(PayOrderDO::getId, paramJSON.getStr("unionOrderId"))
                        .or().eq(PayOrderDO::getMchOrderId, paramJSON.getStr("unionOrderId"))
                        .or().eq(PayOrderDO::getChannelOrderNo, paramJSON.getStr("unionOrderId"));
            });
        }

        wrapper.orderByDesc(PayOrderDO::getCreateTime);

        return page(iPage, wrapper);
    }

    /**
     * 计算支付订单商家入账金额
     * 商家订单入账金额 （支付金额 - 手续费 - 退款金额 - 总分账金额）
     *
     * @author terrfly
     * @date 2021/8/26 16:39
     */
    public Long calMchIncomeAmount(PayOrderDO dbPayOrder, DivisionReceiverDTO dto) {
        //商家订单入账金额 （支付金额 - 手续费 - 退款金额 - 总分账金额）
        Long mchIncomeAmount = dbPayOrder.getAmount()
                - dbPayOrder.getMchFeeAmount() - dbPayOrder.getRefundAmount();

        return mchIncomeAmount;
    }
}
